package cn.javaxc.mvcwork.controller.web;
import cn.javaxc.mvcwork.framework.actions.TActionContext;
import cn.javaxc.mvcwork.framework.database.ConnectionElement;
import cn.javaxc.mvcwork.controller.MVCConfig;
import cn.javaxc.model.base.SQLMap;
import cn.javaxc.mvcwork.util.common.*;
import java.lang.reflect.Method;
import java.sql.*;
import java.text.DateFormat;
import java.util.*;
import javax.servlet.http.*;
import cn.javaxc.mvcwork.control.web.*;
import org.apache.ibatis.session.RowBounds;





public class PagedListInfo extends RowBounds{

  public final static int DEFAULT_ITEMS_PER_PAGE = 20;
  public final static int LIST_VIEW = 1;
  public final static int LIST_ALL = 3;
  public final static int DETAILS_VIEW = 2;
	int rollPage = 11;
  private int mode = LIST_VIEW;
  private String link = "";
  private String id = null;
  private String columnToSortBy = null;
  private String sortOrder = null;
  private String orderByStatement = null;
  private int itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
  private int maxRecords = 0;
  private int currentOffset = 0;
  private int previousOffset = 0;
  private boolean enableJScript = false;
  private boolean showForm = true;
  private boolean resetList = true;
  private String alternateSort = null;
  private HashMap savedCriteria = new HashMap();

  //specifically for modules using the contactsList

  private boolean expandedSelection = false;
  private boolean scrollReload = false;
  private boolean isValid = false;

  // added for Portlets
  private String namespace = "";
  private HashMap renderParameters = null;

  private SQLMap searchParas=new SQLMap();
	private boolean hasSelectItems=true;


  
  public PagedListInfo() {
  }


  
  public int getMode() {
    return mode;
  }


  
  public void setMode(int tmp) {
//    if (mode == LIST_VIEW && tmp == DETAILS_VIEW) {
//      previousOffset = currentOffset;
//    }
//    if (mode == DETAILS_VIEW && tmp == LIST_VIEW) {
//      currentOffset = previousOffset;
//    }
    this.mode = tmp;
  }


  
  public void setColumnToSortBy(String tmp) {
    this.columnToSortBy = tmp;
  }


  
  public void setEnableJScript(boolean enableJScript) {
    this.enableJScript = enableJScript;
  }


  
  public void setSortOrder(String tmp) {
    this.sortOrder = tmp;
  }


  
  public void setShowForm(boolean showForm) {
    this.showForm = showForm;
  }


  
  public void setResetList(boolean resetList) {
    this.resetList = resetList;
  }





  
  public boolean getExpandedSelection() {
    return expandedSelection;
  }


  
  public void setExpandedSelection(boolean expandedSelection) {
    this.expandedSelection = expandedSelection;
    this.setItemsPerPage(DEFAULT_ITEMS_PER_PAGE);
  }


  
  public boolean getScrollReload() {
    return scrollReload;
  }


  
  public void setScrollReload(boolean tmp) {
    this.scrollReload = tmp;
  }


  
  public void setItemsPerPage(int tmp) {
	  if (tmp<1||tmp>1000){
		tmp=DEFAULT_ITEMS_PER_PAGE;
	  }
    if (tmp > itemsPerPage || tmp == -1) {
      resetList();
    }
    this.itemsPerPage = tmp;
  }

  public String getCurrentLetter() {
    return "";
  }
  



  
  public String getId() {
    return id;
  }


  
  public void setId(String id) {
    this.id = id;
  }


  
  public void setItemsPerPage(String tmp) {
    try {
      this.setItemsPerPage(Integer.parseInt(tmp));
    } catch (Exception e) {
    }
  }


  
  public void setLink(String tmp) {
    this.link = tmp;
  }

  public String getLink() {
    return link;
  }

  
  public void setMaxRecords(int tmp) {
    maxRecords = tmp;
    if (System.getProperty("DEBUG") != null) {
      System.out.println("PagedListInfo-> Records in table: " + maxRecords);
    }
    //Check to see if the currentOffset is greater than maxRecords,
    //if so, find a nice page break to stop on
    if (maxRecords <= currentOffset && maxRecords > 0 && getItemsPerPage() != -1)
    {
      currentOffset = maxRecords;

      while (((currentOffset % getItemsPerPage()) > 0) && (currentOffset > 0)) {
        --currentOffset;
      }
      if (System.getProperty("DEBUG") != null) {
        System.out.println(
            "PagedListInfo-> Offset reduced to: " + currentOffset);
      }
      //Check to see if the page break has any records to display, otherwise
      //go back a page
      if (currentOffset == maxRecords) {
        currentOffset = currentOffset - getItemsPerPage();
      }
    }
  }


  


  
  public void setCurrentOffset(int tmp) {
    if (tmp < 0) {
      this.currentOffset = 0;
    } else {
      this.currentOffset = tmp;
    }
  }


  
  public void setCurrentOffset(String tmp) {
    try {
      this.setCurrentOffset(Integer.parseInt(tmp));
    } catch (Exception e) {
    }
  }
  
  public boolean setParameters(HttpServletRequest request) {
    //check for multiple pagedLists on a single page
    if (request.getParameter("pagedListInfoId") != null &&
        !(request.getParameter("pagedListInfoId").equals("")) &&
        this.getId() != null && !"".equals(this.getId().trim()) &&
        !(request.getParameter("pagedListInfoId").equals("null")) &&
        !(request.getParameter("pagedListInfoId").equals(
            this.getId()))) {
      return false;
    }
	return doParameters(request);
  }
  public boolean doParameters(HttpServletRequest request) {
    Enumeration parameters = request.getParameterNames();
    boolean reset = false;

    


    // User has specified a page number to view
    // This will be used as a parameter in the query
    String tmpCurrentPage = request.getParameter("pageNo");
    if (tmpCurrentPage != null) {
      try {
        if (getItemsPerPage() == -1) {
          throw new java.lang.NumberFormatException("All records in one page");
        }
        this.setCurrentOffset(
            (Integer.parseInt(tmpCurrentPage) - 1) * getItemsPerPage());
      } catch (java.lang.NumberFormatException e) {
        this.setCurrentOffset(0);
      }
    }

    //User is changing the number of items to display -- needs to be done after the
    //page select
    String tmpItemsPerPage = request.getParameter("pageSize");
    if (tmpItemsPerPage != null) {
      this.setItemsPerPage(tmpItemsPerPage);
    }



    //The user has selected an offset to go to... could be through a
    //page element that calculates the offset per page
    String tmpCurrentOffset = request.getParameter("offset");
    if (tmpCurrentOffset != null) {
      this.setCurrentOffset(tmpCurrentOffset);
    }

	if(request.getParameter("orderBy")!=null){
		setColumnToSortBy(request.getParameter("orderBy"));
	}
	if(request.getParameter("sortBy")!=null){
		setSortOrder(request.getParameter("sortBy"));
	}

	

    return true;
  }





  
  public void setDefaultSort(String column, String order) {
    if (!this.hasSortConfigured()) {
      this.setColumnToSortBy(column);
      this.setSortOrder(order);
    }
  }

  public void setNamespace(String namespace) {
    this.namespace = namespace;
  }

  public void setRenderParameters(HashMap renderParameters) {
    this.renderParameters = renderParameters;
  }

  
  public String getColumnToSortBy() {
    return columnToSortBy;
  }
  public String getColumnToSortBy(String def) {
    return StringUtils.isNullData(columnToSortBy)?def:columnToSortBy;
  }

  
  public String getSortOrder() {
    return getSortOrder("");
  }
  public String getSortOrder(String _order) {
    return sortOrder!=null?sortOrder:_order;
  }


  
  public int getItemsPerPage() {
    if (mode == DETAILS_VIEW) {
      return 1;
    }
    return itemsPerPage;
  }


  
  public int getMaxRecords() {
    return maxRecords;
  }


  


  
  public int getCurrentOffset() {
    return currentOffset;
  }


  
  public boolean getEnableJScript() {
    return enableJScript;
  }



  
  public String getListPropertiesHeader(String formName) {
    if (showForm) {
      if (expandedSelection) {
        link += "&pagedListSectionId=" + id;
      }
      return ("<form name=\"" + formName + "\" action=\"" + link + "\" method=\"post\">");
    } else {
      return "";
    }

  }


  
  public String getListPropertiesFooter() {
    if (showForm) {
      return ("</form>");
    } else {
      return "";
    }
  }




  
  public String getItemsPerPageEntry(String name,String allLabel) {
    HtmlSelect itemSelect = new HtmlSelect();
    itemSelect.addItem("10");
    itemSelect.addItem("12");
    itemSelect.addItem("20");
    itemSelect.addItem("50");
    itemSelect.addItem("100");
    itemSelect.addItem("500");
	itemSelect.addItem("1000");
	if(false){
		itemSelect.addItem("-1", allLabel);
	}
//    itemSelect.setJsEvent("onChange=\"doPagedList('ttp','"+getLink()+"');\"");
    return (itemSelect.getHtml(name, getItemsPerPage()));
    //return("Items per page <input type=\"text\" name=\"items\" value=\"" + getItemsPerPage() + "\" size=\"3\">");
  }


  
  public int getNumberOfPages() {
    if (getItemsPerPage() != -1) {
      return (int) Math.ceil((double) maxRecords / (double) getItemsPerPage());
    }
    return 1;
  }


  
  public String getNumericalPageLinks() {
    int totalPages = this.getNumberOfPages();
	int nowPage=(getCurrentOffset() / getItemsPerPage()) + 1;
	int now_cool_page = rollPage / 2;
	int now_cool_page_ceil = (int)Math.ceil(now_cool_page);
    StringBuffer links = new StringBuffer();
	int page=1;
    if (totalPages > 1) {
      for (int i = 1; i <= rollPage; i++) {
			if ((nowPage - now_cool_page) <= 0) {
                page = i;
            } else if ((nowPage + now_cool_page - 1) >= totalPages) {
                page = totalPages - rollPage + i;
            } else {
                page = nowPage - now_cool_page_ceil + i;
            }
            if (page > 0 && page != nowPage) {
                if (page <= totalPages) {
				  links.append(
					  "<li><a href=\"" + link + "&offset=" + ((page - 1) * getItemsPerPage()) + "\"> " + page + " </a></li>");
                } else {
                    break;
                }
            } else {
                if (page > 0 && totalPages != 1) {
                    links.append( "<li class=\"active\"><a href=\"#\">" + page + "</a></li>");
                }
            }
      }
    }
    return links.toString();
  }



  

  public String getPreviousPageLink(String linkOn, String linkOff, String formName, HttpServletResponse response) {
    StringBuffer result = new StringBuffer();
    if (currentOffset > 0 && getItemsPerPage() != -1) {
      int newOffset = currentOffset - getItemsPerPage();

        if (this.getNumberOfPages() > this.rollPage && ((getCurrentOffset() / getItemsPerPage()) + 1 - rollPage / 2) >= 1) {
			result.append("<li><a href=\"" + link+"&offset=0\">1...</a></li>");
        }
		result.append("<li><a href=\"" + link+ "&offset=" + (newOffset > 0 ? newOffset : 0) + "\"><i class='ace-icon fa fa-angle-double-left'></i></a></li>");
        return result.toString();
    } else {
      return linkOff;
    }
  }


  


  public String getNextPageLink(String linkOn, String linkOff, String formName, HttpServletResponse response) {
    StringBuffer result = new StringBuffer();
    if ((currentOffset + getItemsPerPage()) < maxRecords && getItemsPerPage() != -1)
    {
     
		result.append("<li><a href=\"" + link +"&offset=" + (currentOffset + getItemsPerPage()) + "\"><i class='ace-icon fa fa-angle-double-right'></i></a></li>");
		result.append("<li><a href=\"" + link +"&offset="+maxRecords+"\">"+getNumberOfPages()+"</a></li>");
        return result.toString();
    } else {
      return linkOff;
    }
  }


  
  // TODO: see where this method is used
  public String getExpandLink(String expandLink, String collapseLink) {
    if (!expandedSelection) {
      return "<a href=\"" + link + "&pagedListInfoId=" + this.getId() + "&pagedListSectionId=" + this.getId() + "\">" + expandLink + "</a>";
    } else {
      return "<a href=\"" + link + "&resetList=true&pagedListInfoId=" + this.getId() + "\">" + collapseLink + "</a>";
    }
  }

  
  public String getExpandLink(String expandLink, String collapseLink, String tmpParams) {
    if (!expandedSelection) {
      return "<a href=\"" + link + "&pagedListInfoId=" + this.getId() + "&pagedListSectionId=" + this.getId() + tmpParams + "\">" + expandLink + "</a>";
    } else {
      return "<a href=\"" + link + "&resetList=true&pagedListInfoId=" + this.getId() + tmpParams + "\">" + collapseLink + "</a>";
    }
  }


  
  public String getSortIcon(String columnName) {
	  if (columnName!=null&&!columnName.isEmpty()){	  
		if (columnName.equals(columnToSortBy)) {
		  if (sortOrder != null && sortOrder.indexOf("desc") > -1) {
			return "<img border=0 src=\""+MVCConfig.getConfig().getWebStatic()+"images/layout/sort-dn.gif\" align=\"bottom\" width=\"12\" height=\"10\" />";
		  } else {
			return "<img border=0 src=\""+MVCConfig.getConfig().getWebStatic()+"images/layout/sort-up.gif\" align=\"bottom\" width=\"12\" height=\"10\" />";
		  }
		} 
	}
      return "";
  }
 public String getDescOrder() {
	if (sortOrder != null && sortOrder.indexOf("desc") > -1) {
		return "";
	}
	return "desc";
 }

  




  



  
  public boolean hasLink() {
    return (link != null && !"".equals(link.trim()));
  }


  


  
  public boolean hasSortConfigured() {
    return (this.getColumnToSortBy() != null && !"".equals(this.getColumnToSortBy()));
  }


  
  public boolean hasSortOrderConfigured() {
    return (this.getSortOrder() != null && !"".equals(this.getSortOrder()));
  }


  
  public void appendSqlSelectHead(Connection db, StringBuffer sqlStatement) {
    if (DatabaseUtils.getType(db) == DatabaseUtils.MSSQL &&
        this.getItemsPerPage() > 0) {
      int x = this.getItemsPerPage() + this.getCurrentOffset();
      sqlStatement.append("SELECT TOP " + x + " ");
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.ORACLE &&
        this.getItemsPerPage() > 0) {
      sqlStatement.append("SELECT * FROM (SELECT ");
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.DB2 &&
        this.getItemsPerPage() > 0) {
      sqlStatement.append("SELECT * FROM (SELECT ROW_NUMBER() OVER (" + orderByStatement + ") AS db_row, ");
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.FIREBIRD &&
        this.getItemsPerPage() > 0) {
      sqlStatement.append("SELECT FIRST " + this.getItemsPerPage() + " ");
      sqlStatement.append("SKIP " + this.getCurrentOffset() + " ");
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.DAFFODILDB &&
        this.getItemsPerPage() > 0) {
      int x = this.getItemsPerPage() + this.getCurrentOffset();
      sqlStatement.append("SELECT TOP (" + x + ") ");
    } else {
      sqlStatement.append("SELECT ");
    }
  }


  
  public void appendSqlTail(Connection db, StringBuffer appendedSqlStatement) {
    StringBuffer sqlStatement = new StringBuffer();
    sqlStatement.append("ORDER BY ");
    //Determine sort order
    //If multiple columns are being sorted, then the sort order applies to all columns
    if (this.getColumnToSortBy().indexOf(",") > -1) {
      StringTokenizer st = new StringTokenizer(this.getColumnToSortBy(), ",");
      while (st.hasMoreTokens()) {
        String column = st.nextToken();
        sqlStatement.append(DatabaseUtils.parseReservedWord(db, column) + " ");
        if (this.hasSortOrderConfigured()) {
          sqlStatement.append(this.getSortOrder() + " ");
        }
        if (st.hasMoreTokens()) {
          sqlStatement.append(",");
        }
      }
    } else {
      sqlStatement.append(DatabaseUtils.parseReservedWord(db, this.getColumnToSortBy()) + " ");
      if (this.hasSortOrderConfigured()) {
        sqlStatement.append(this.getSortOrder() + " ");
      }
    }
    // Keep a handle on just the order by clause for use by appendSqlHead
    orderByStatement = sqlStatement.toString();

    //Determine items per page for PostgreSQL
    if (DatabaseUtils.getType(db) == DatabaseUtils.POSTGRESQL) {
      if (this.getItemsPerPage() > 0) {
        sqlStatement.append("LIMIT " + this.getItemsPerPage() + " ");
      }
      sqlStatement.append("OFFSET " + this.getCurrentOffset() + " ");
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.INTERBASE &&
    		this.getItemsPerPage() > 0 ) {
    	sqlStatement.append( " ROWS " + this.getCurrentOffset() + " TO " +
    			( this.getItemsPerPage() + this.getCurrentOffset() ) );
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.ORACLE) {
      if (this.getItemsPerPage() > 0) {
        //sqlStatement.append(") " +
        //    "WHERE ROWNUM BETWEEN " + this.getCurrentOffset() + " AND " +
        //    (this.getCurrentOffset() + this.getItemsPerPage()) + " ");
        sqlStatement.append(") " +
            "WHERE ROWNUM <= " +
            (this.getCurrentOffset() + this.getItemsPerPage()) + " ");

      }
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.DB2) {
      if (this.getItemsPerPage() > 0) {
        sqlStatement.append(
            "FETCH FIRST " + (this.getItemsPerPage() + this.getCurrentOffset()) + " ROWS ONLY) AS db_row_numbers " +
                "WHERE db_row > " + this.getCurrentOffset() + " AND db_row <= " + (this.getCurrentOffset() + this.getItemsPerPage()) + " ");
      }
    } else if (DatabaseUtils.getType(db) == DatabaseUtils.MYSQL) {
      if (this.getItemsPerPage() > 0) {
        sqlStatement.append("LIMIT " + this.getCurrentOffset() + "," + this.getItemsPerPage() + " ");
      }
    }
    appendedSqlStatement.append(sqlStatement);
  }


  
  public void doManualOffset(Connection db, ResultSet rs) throws SQLException {
    if (this.getItemsPerPage() > 0){
      DatabaseUtils.skipRowsManual(db, rs, this.getCurrentOffset());
    }
  }

  public void doManualOffset(Connection db, PreparedStatement pst) throws SQLException{
    if (this.getItemsPerPage() > 0){
      DatabaseUtils.doManualLimit(db, pst, this.getCurrentOffset() + this.getItemsPerPage());
    }
  }

  
  public String toString() {
    StringBuffer sb = new StringBuffer();
//    sb.append("Link: " + link + "\r\n");
    sb.append("Sort Column: " + columnToSortBy + "<br/>\r\n");
    sb.append("Sort Order: " + sortOrder + "<br/>\r\n");
    sb.append("Items per page: " + getItemsPerPage() + "&nbsp;"+hasSelectItems+"&nbsp;");
    sb.append("Total record count: " + maxRecords + "<br/>\r\n");
    sb.append("Current offset record: " + currentOffset + "<br/>\r\n");
	sb.append(searchParas);
    return sb.toString();
  }


  
  private void resetList() {
    this.setCurrentOffset(0);
    previousOffset = 0;
  }


  
  public int getPageSize() {
    if ((currentOffset + getItemsPerPage()) < maxRecords && getItemsPerPage() != -1)
    {
      // current = 0
      // items = 10
      // max = 17
      // 0 + 10 < 17
      return (currentOffset + getItemsPerPage());
    } else {
      // current = 10
      // items = 10
      // max = 17
      return (maxRecords);
    }
  }

 

	public SQLMap getSearchParas(){
		return this.searchParas;
	}
	public void setSearchParas(SQLMap searchParas){
		this.searchParas=searchParas;
	}
	public SQLMap getMap(){
		return getSearchParas();
	}
	public boolean hasSelectItems(){
		return this.hasSelectItems;
	}
	public void setSelectItems(boolean hasSelectItems){
		this.hasSelectItems=hasSelectItems;
	}
    public int getOffset() {
		if (getMode()==LIST_ALL){
			return NO_ROW_OFFSET;
		}
        return getCurrentOffset();
    }

    public int getLimit() {
		if (getMode()==LIST_ALL){
			return NO_ROW_LIMIT;
		}
        return getItemsPerPage();
    }

}
